# coding:utf-8

from ctypes import *
import re
from . import TPIClient as tpi


TPI_HCON = tpi.TPI_HCON
TPI_HRECORDSET = tpi.TPI_HRECORDSET
TPI_HEVENT = tpi.TPI_HEVENT
HTABLE = tpi.HTABLE
HCOL = tpi.HCOL
HSTIME32 = tpi.HSTIME32
INT64 = tpi.INT64

HS_Query = tpi.HS_Query
HS_TABLE_HEAD = tpi.HS_TABLE_HEAD
HS_TABLE_FIELD = tpi.HS_TABLE_FIELD
HS_FIELD_MAP_ITEM = tpi.HS_FIELD_MAP_ITEM
_HS_TABLE_HEAD_Z3950 = tpi._HS_TABLE_HEAD_Z3950
TPI_IP = tpi.TPI_IP
TPI_LOGIN_PARA = tpi.TPI_LOGIN_PARA
TPI_DATA = tpi.TPI_DATA
TPI_VAR_LONGS = tpi.TPI_VAR_LONGS
TPI_TABLE_INFO = tpi.TPI_TABLE_INFO
TPI_FILE_REC_OUTPUT = tpi.TPI_FILE_REC_OUTPUT
TPI_ADD_RECORD = tpi.TPI_ADD_RECORD
TPI_BULK_SET_RECORD = tpi.TPI_BULK_SET_RECORD
TPI_DISKINFO = tpi.TPI_DISKINFO
TPI_DIRINFO = tpi.TPI_DIRINFO
TPI_COPYFILE = tpi.TPI_COPYFILE
TPI_INI_READWRITE = tpi.TPI_INI_READWRITE
RECORDSET = tpi.RECORDSET
MemOpt = tpi.MemOpt
CONFIG_PARAM = tpi.CONFIG_PARAM
USP_FIELD = tpi.USP_FIELD
USP_FIELDINFO_RET = tpi.USP_FIELDINFO_RET
TPI_TABLE_STORAGESPACE = tpi.TPI_TABLE_STORAGESPACE
TPI_OPEN_RECORDSET = tpi.TPI_OPEN_RECORDSET
TPI_EVENT_RUNTYPE = tpi.TPI_EVENT_RUNTYPE
TPI_SERVER_SYSTEMINFO = tpi.TPI_SERVER_SYSTEMINFO
TPI_SERVER_SYSTEMINFO_EX = tpi.TPI_SERVER_SYSTEMINFO_EX
HS_ACCOUNT_DBNAME = tpi.HS_ACCOUNT_DBNAME
TPI_ACCOUNT_DBRIGHT = tpi.TPI_ACCOUNT_DBRIGHT

INVALID = 0x01
INSERT = 0x02
DELETE = 0x03
UPDATE = 0x04
REPLACE = 0x05
SELECT = 0x06
OTHER = 0x07

def connect(host = '127.0.0.1', port = 4567, user = 'DBOWN', passwd = ''):
    conn = connection()
    userip = tpi.TPI_IP()
    param = tpi.TPI_LOGIN_PARA()
    userip.szIp = host
    param.szUserName = user
    param.szPassWord = passwd
    param.UserIp = userip
    errcode = c_int(0)
    conn.hcon = tpi.TPI_OpenCon(host, port, param, byref(errcode))
    conn.openend = 1
    conn.errcode = errcode.value
    return conn

class connection:
    def __init__(self):
        self.hcon = None
        self.openend = 0
        self.errcode = 0

    def close(self):
        self.hcon = tpi.TPI_CloseCon(self.hcon)
        self.openend = 0
        self.errcode = 0

    def commit(self):
        pass

    def rollback(self):
        pass

    def cursor(self):
        cur = cursor()
        cur.conn = self
        return cur

def _ksqlformat(format, args):
    if format == None:
        return ''
    if args != None:
        substr = format
        ksql = ''
        begin = 0
        end = 0
        next = 0
        key = ''
        value = ''
        count = 0
        patterns = r'[%?:\\\']'
        match = re.search(patterns, substr)
        if not match:
            return substr
        pos = match.start()
        while pos >= 0:
            if substr[pos] == '\\':
                end = pos
                next = pos + 1
                ksql += substr[begin:end]
                ksql += substr[next]
                next += 1
            elif substr[pos] == '\'':
                end = substr.find('\'', pos + 1)
                next = end + 1
                ksql += substr[begin:next]
            else:
                if substr[pos] == '%':
                    end = pos
                    next = pos + 1
                    if substr[next] == '(':
                        tmp = substr.find(')', next)
                        key = substr[next + 1:tmp]
                        value = args.get(key)
                        next = tmp + 1
                    else:
                        key = count
                        value = args[key]
                    count += 1
                    ksql += substr[begin:end]
                    ksql += value
                    if substr[next] == 's':
                        next += 1
                elif substr[pos] == '?':
                    end = pos
                    next = pos + 1
                    key = count
                    value = args[key]
                    count += 1
                    ksql += substr[begin:end]
                    ksql += value
                elif substr[pos] == ':':
                    end = pos
                    next = pos + 1
                    tmp = substr.find(',', next)
                    if substr[next:tmp].isdigit():
                        key = count
                        value = args[key]
                    else:
                        key = substr[next:tmp]
                        value = args.get(key)
                    next = tmp
                    count += 1
                    ksql += substr[begin:end]
                    ksql += value
            substr = substr[next:]
            match = re.search(patterns, substr)
            if not match:
                break
            pos = match.start()
        ksql += substr
    else:
        ksql = format
    return ksql

class cursor:
    def __init__(self):
        self.conn = None
        self.hset = 0
        self.opend = 0
        self.colcount = 0
        self.rowcount = 0
        self.arraysize = 1
        self.errcode = 0

    def _getstatementtype(self, ksql):
        patterns = r'[ \\r\\n\\t]'
        str = ksql.lower()
        pos = re.search(patterns, str).start()
        while pos == 0:
            str = str[1:]
            match = re.search(patterns, str)
            if not match:
                break
            pos = match.start()
        if str == '':
            type = INVALID
        if str[0:len("select")] == "select" or str[0:len("varselect")] == "varselect":
            type = SELECT
        elif str[0:len("insert")] == "insert":
            type = INSERT
        elif str[0:len("update")] == "update":
            type = UPDATE
        elif str[0:len("delete")] == "delete":
            type = DELETE
        elif str[0:len("replace")] == "replace":
            type = REPLACE
        else:
            type = OTHER
        return type

    def _execute(self, ksql, args, multiple, bunicode):
        type = self._getstatementtype(ksql)
        if type == INVALID:
            self.errcode = -1
            return
        errcode = c_int(0)
        if multiple == 0:
            sql = _ksqlformat(ksql, args)
            if type == SELECT:
                self.close()
                self.hset = tpi.TPI_OpenRecordSet(self.conn.hcon, sql, errcode, bunicode)
                self.opend = 1
                self.colcount = tpi.TPI_GetFieldCount(self.hset)
                self.rowcount = tpi.TPI_GetRecordSetCount(self.hset)
                self.errcode = errcode.value
            else:
                self.errcode = tpi.TPI_ExecSQL(self.conn.hcon, sql, bunicode)
        elif multiple == 1:
            if isinstance(args, tuple) or isinstance(args, list):
                for each in args:
                    sql = _ksqlformat(ksql, each)
                    if type == SELECT:
                        self.close()
                        self.hset = tpi.TPI_OpenRecordSet(self.conn.hcon, sql, errcode, bunicode)
                        self.opend = 1
                        self.colcount = tpi.TPI_GetFieldCount(self.hset)
                        self.rowcount = tpi.TPI_GetRecordSetCount(self.hset)
                        self.errcode = errcode.value
                    else:
                        self.errcode = tpi.TPI_ExecSQL(self.conn.hcon, sql, bunicode)
        else:
            pass

    def _iternext(self):
        flag = tpi.TPI_IsEOF(self.hset)
        if flag:
            self.errcode = flag
            return
        self.errcode = tpi.TPI_MoveNext(self.hset)
        self.rowcount -= 1

    def _fetchonerow(self):
        row = [''] * self.colcount
        nfieldtype = 0
        pfieldname = create_unicode_buffer(tpi.HS_FIELD_NAME_LEN)
        nullbuf = ''
        errbuf = '<!!>'
        errnobuf = '<!!>#<ErrorCode=%d}>#'
        charbufsize = 1024
        charbuf = create_string_buffer(charbufsize)
        wcharbufsize = 1024 * sizeof(c_wchar)
        wcharbuf = create_unicode_buffer(wcharbufsize)
        
        nread = 0
        for i in range(0, self.colcount):
            tpi.TPI_GetFieldName(self.hset, i, pfieldname)
            nfieldtype = tpi.TPI_GetFieldTypeByName(self.hset, pfieldname)
            if nfieldtype == tpi.HSD_SOB:
                nread = tpi.TPI_GetBLob(self.hset, i, 0, 0, charbuf, charbufsize)
                if nread < 0:
                    row[i] = errbuf
                    break
                row[i] = charbuf.value
            elif nfieldtype == tpi.HSD_LOB \
                    or nfieldtype == tpi.HSD_DOB:
                del(charbuf)
                charbufsize = 10*1024*1024
                charbuf = create_string_buffer(charbufsize)
                nread = tpi.TPI_GetBLob(self.hset, i, 0, 0, charbuf, charbufsize)
                if nread < 0:
                    row[i] = errbuf
                    break
                row[i] = charbuf.value
            elif (#nfieldtype == tpi.HSD_VIRTUAL
                    #or nfieldtype == tpi.HSD_TNAME
                    #or nfieldtype == tpi.HSD_TANAME
                    #or nfieldtype == tpi.HSD_RECORDID
                    #or nfieldtype == tpi.HSD_RELEVANT
                    #or nfieldtype == tpi.HSD_SNAPSHOT
                    nfieldtype == tpi.HSD_SMART
                    or nfieldtype == tpi.HSD_XML_VIRTUAL
                    or nfieldtype == tpi.HSD_NULL):
                row[i] = nullbuf
            else:
                nread = tpi.TPI_GetFieldValue(self.hset, i, wcharbuf, wcharbufsize)
                if nread == tpi.TPI_ERR_BUFFER:
                    datalen = tpi.TPI_GetColDataLen(self.conn.hcon, self.hset, i)+1
                    del(wcharbuf)
                    wcharbufsize = (datalen + 1) * sizeof(c_wchar)
                    wcharbuf = create_unicode_buffer(wcharbufsize)
                    nread = tpi.TPI_GetFieldValue(self.hset, i, wcharbuf, wcharbufsize)

                if nread >= 0:
                    try:
                        row[i] = wcharbuf.value
                    except ValueError:
                        pos = 0
                        temp = ''
                        buf = ''
                        for pos in range(wcharbufsize):
                            try:
                                temp = wstring_at(byref(wcharbuf, pos * sizeof(c_wchar)), 1)
                                if '\0' == temp:
                                    break
                                buf += temp
                                continue
                            except ValueError:
                                buf += '?'
                        row[i] = buf
                elif (nread == tpi.TPI_ERR_GETCOLDATALEN
                        or nread == tpi.TPI_ERR_GETCOLDATA
                        or nread == tpi.TPI_ERR_FIELD_NORIGHTS
                        or nread == tpi.TPI_ERR_FIELD_NAME
                        or nread == tpi.TPI_ERR_FIELD_INDEX):
                    row[i] = errbuf
                    break
                else:
                    row[i] = errnobuf % nread
                    break

        del(pfieldname)
        del(charbuf)
        del(wcharbuf)
        self._iternext()

        if nread < 0:
            ex = Exception(nread)
            raise ex

        return row

    def close(self):
        if self.opend and self.hset > 0:
            tpi.TPI_CloseRecordSet(self.hset)
        self.hset = 0
        self.opend = 0
        self.colcount = 0
        self.rowcount = 0
        self.arraysize = 1
        self.errcode = 0

    def execute(self, ksql, args = None, bunicode = False):
        self._execute(ksql, args, 0, bunicode)

    def executemany(self, ksql, args = None, bunicode = False):
        self._execute(ksql, args, 1, bunicode)

    def fetchone(self):
        return self._fetchonerow()

    def fetchmany(self, size = 1):
        if size != self.arraysize:
            self.arraysize = size
        rows = []
        for each in range(0, self.arraysize):
            row = self._fetchonerow()
            rows.append(row)
        return rows

    def fetchall(self):
        rows = []
        for each in range(0, self.rowcount):
            row = self._fetchonerow()
            rows.append(row)
        return rows

class TPIClient:
    def __init__(self, conn = None, cur = None):
        self.conn = conn
        self.cur = cur

    def setConnection(self, conn):
        self.conn = conn

    def getConnection(self):
        return self.conn

    def setCursor(self, cur):
        self.cur = cur

    def getCursor(self):
        return self.cur

    def getErrorMsg(self, errcode):
        size = c_int(128)
        buf = create_unicode_buffer(size.value)
        while True:
            ret = tpi.TPI_GetErrorMsg(errcode, buf, size)
            if ret == tpi.TPI_ERR_BUFFER:
                del (buf)
                size.value *= 2
                buf = create_unicode_buffer(size.value)
                continue
            elif ret >= 0:
                try:
                    return (ret, buf.value)
                except ValueError:
                    pos = 0
                    try:
                        for pos in range(size.value):
                            wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                    except ValueError:
                        if 0 == pos:
                            return (ret, "")
                        pos = pos - 1
                        return (ret, wstring_at(buf, pos))
            else:
                return (ret,)

    def writeLog(self, errinfo):
        pass

    def getLogFilePath(self):
        size = tpi.MAX_PATH
        buf = create_unicode_buffer(size)
        while True:
            ret = tpi.TPI_GetLogFilePath(buf, size)
            if ret == tpi.TPI_ERR_BUFFER:
                del (buf)
                size *= 2
                buf = create_unicode_buffer(size)
                continue
            elif ret >= 0:
                try:
                    return (ret, buf.value)
                except ValueError:
                    pos = 0
                    try:
                        for pos in range(size):
                            wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                    except ValueError:
                        if 0 == pos:
                            return (ret, "")
                        pos = pos - 1
                        return (ret, wstring_at(buf, pos))
            else:
                return (ret,)

    def openCon(self, host, port, loginpara, extype = None):
        errcode = c_int(0)
        conn = connection()
        conn.hcon = tpi.TPI_OpenCon(host, port, loginpara, errcode, extype)
        conn.openend = 1
        return (errcode.value, conn)

    def openCon2(self, host, port, loginpara, extype = None):
        errcode = c_int(0)
        conn = connection()
        conn.hcon = tpi.TPI_OpenCon2(host, port, byref(loginpara), errcode, extype)
        conn.openend = 1
        return (errcode.value, conn)

    def reconnect(self):
        ret = tpi.TPI_Reconnect(self.conn.hcon)
        return (ret,)

    def closeCon(self):
        ret = tpi.TPI_CloseCon(self.conn.hcon)
        return (ret,)

    def isValidCon(self):
        ret = tpi.TPI_IsValidCon(self.conn.hcon)
        return (ret,)

    def isActiveCon(self):
        ret = tpi.TPI_IsActiveCon(self.conn.hcon)
        return (ret,)

    def refreshCon(self, seconds):
        ret = tpi.TPI_RefreshCon(self.conn.hcon, seconds)
        return (ret,)

    def checkServerState(self):
        ret = tpi.TPI_CheckServerState(self.conn.hcon)
        return (ret,)

    def execSQL(self, sql, args = None, bunicode = False):
        ksql = _ksqlformat(sql, args)
        ret = tpi.TPI_ExecSQL(self.conn.hcon, ksql, bunicode)
        return (ret,)

    def execMgrSql(self, sql, args = None, bunicode = False):
        ksql = _ksqlformat(sql, args)
        eventhandle = TPI_HEVENT(0)
        ret = tpi.TPI_ExecMgrSql(self.conn.hcon, ksql, eventhandle, bunicode)
        if ret >= 0:
            ret = eventhandle.value
        return (ret,)

    def checkSql(self, sql, args = None, bunicode = False):
        ksql = _ksqlformat(sql, args)
        ret = tpi.TPI_CheckSql(self.conn.hcon, ksql, bunicode)
        return (ret,)

    def getTableCount(self):
        ret = tpi.TPI_GetTableCount(self.conn.hcon)
        return (ret,)

    def getTableNameBySn(self, sn):
        tablename = create_unicode_buffer(tpi.TABLENAME_LENGTH)
        ret = tpi.TPI_GetTableNameBySn(self.conn.hcon, sn, tablename)
        if ret >= 0:
            try:
                return (ret, tablename.value)
            except ValueError:
                pos = 0
                try:
                    for pos in range(tpi.TABLENAME_LENGTH):
                        wstring_at(byref(tablename, pos * sizeof(c_wchar)), 1)
                except ValueError:
                    if 0 == pos:
                        return (ret, "")
                    pos = pos - 1
                    return (ret, wstring_at(tablename, pos))
        else:
            return (ret,)

    def tableNameExists(self, tablename):
        ret = tpi.TPI_TableNameExists(self.conn.hcon, tablename)
        return (ret,)

    def getViewCount(self):
        ret = tpi.TPI_GetViewCount(self.conn.hcon)
        return (ret,)

    def getViewNameBySn(self, sn):
        viewname = create_unicode_buffer(tpi.TABLENAME_LENGTH)
        ret = tpi.TPI_GetViewNameBySn(self.conn.hcon, sn, viewname)
        if ret >= 0:
            try:
                return (ret, viewname.value)
            except ValueError:
                pos = 0
                try:
                    for pos in range(tpi.TABLENAME_LENGTH):
                        wstring_at(byref(viewname, pos * sizeof(c_wchar)), 1)
                except ValueError:
                    if 0 == pos:
                        return (ret, "")
                    pos = pos - 1
                    return (ret, wstring_at(viewname, pos))
        else:
            return (ret,)

    def viewNameExists(self, viewname):
        ret = tpi.TPI_ViewNameExists(self.conn.hcon, viewname)
        return (ret,)

    def getViewSQL(self, viewname, bunicode = False):
        buflen = c_int(1024)
        viewsql = create_unicode_buffer(buflen.value)
        ret = tpi.TPI_GetViewSQL(self.conn.hcon, viewname, viewsql, buflen, bunicode)
        if ret >= 0:
            try:
                return (ret, viewsql.value)
            except ValueError:
                pos = 0
                try:
                    for pos in range(buflen.value):
                        wstring_at(byref(viewsql, pos * sizeof(c_wchar)), 1)
                except ValueError:
                    if 0 == pos:
                        return (ret, "")
                    pos = pos - 1
                    return (ret, wstring_at(viewsql, pos))
        else:
            return (ret,)

    def refreshTable(self):
        ret = tpi.TPI_RefreshTable(self.conn.hcon)
        return (ret,)

    def openRecordSet(self, sql, args = None, exectype = 0, bunicode = False):
        cur = cursor()
        sql = _ksqlformat(sql, args)
        errcode = c_int(exectype)
        hset = tpi.TPI_OpenRecordSet(self.conn.hcon, sql, errcode, bunicode)
        if errcode.value >= 0:
            cur.conn = self.conn
            cur.hset = hset
            cur.opend = 1
            cur.colcount = tpi.TPI_GetFieldCount(hset)
            cur.rowcount = tpi.TPI_GetRecordSetCount(hset)
            return (errcode.value, cur)
        else:
            return (errcode.value,)

    def openRecordSetEx(self, sql, args = None, exectype = None, flag = None, waitsecond = None, bunicode = False):
        cur = cursor()
        sql = _ksqlformat(sql, args)
        errcode = c_int(0)
        hset = tpi.TPI_OpenRecordSetEx(self.conn.hcon, sql, errcode, exectype, flag, waitsecond, bunicode)
        if errcode.value >= 0:
            cur.conn = self.conn
            cur.hset = hset
            cur.opend = 1
            cur.colcount = tpi.TPI_GetFieldCount(hset)
            cur.rowcount = tpi.TPI_GetRecordSetCount(hset)
            return (errcode.value, cur)
        else:
            return (errcode.value,)

    def openRecordSet2(self, info, bunicode = False):
        cur = cursor()
        errcode = c_int(0)
        hset = tpi.TPI_OpenRecordSet2(self.conn.hcon, byref(info), errcode, bunicode)
        if errcode.value >= 0:
            cur.conn = self.conn
            cur.hset = hset
            cur.opend = 1
            cur.colcount = tpi.TPI_GetFieldCount(hset)
            cur.rowcount = tpi.TPI_GetRecordSetCount(hset)
            return (errcode.value, cur)
        else:
            return (errcode.value,)

    def closeRecordSet(self):
        ret = tpi.TPI_CloseRecordSet(self.cur.hset)
        return (ret,)

    def closeRecordSetEx(self, flag = None):
        ret = tpi.TPI_CloseRecordSetEx(self.cur.hset)
        return (ret,)

    def validateQuery(self):
        ret = tpi.TPI_ValidateQuery(self.cur.hset)
        return (ret,)

    def isValidRecordset(self):
        ret = tpi.TPI_IsValidRecordset(self.cur.hset)
        return (ret,)

    def setHitWordMarkFlag(self, prefix, postfix):
        ret = tpi.TPI_SetHitWordMarkFlag(self.cur.hset, prefix, postfix)
        return (ret,)

    def getRecordSet(self):
        recordset = tpi.RECORDSET()
        ret = tpi.TPI_GetRecordSet(self.cur.hset, byref(recordset))
        if ret >= 0:
            return (ret, recordset)
        else:
            return (ret,)

    def getRecordSetCount(self):
        ret = tpi.TPI_GetRecordSetCount(self.cur.hset)
        return (ret,)

    def moveFirst(self):
        ret = tpi.TPI_MoveFirst(self.cur.hset)
        return (ret,)

    def moveNext(self):
        ret = tpi.TPI_MoveNext(self.cur.hset)
        return (ret,)

    def movePrev(self):
        ret = tpi.TPI_MovePrev(self.cur.hset)
        return (ret,)

    def moveLast(self):
        ret = tpi.TPI_MoveLast(self.cur.hset)
        return (ret,)

    def move(self, pos):
        ret = tpi.TPI_Move(self.cur.hset, pos)
        return (ret,)

    def isEOF(self):
        ret = tpi.TPI_IsEOF(self.cur.hset)
        return (ret,)

    def isBOF(self):
        ret = tpi.TPI_IsBOF(self.cur.hset)
        return (ret,)

    def addNew(self):
        ret = tpi.TPI_AddNew(self.cur.hset)
        return (ret,)

    def delete(self):
        ret = tpi.TPI_Delete(self.cur.hset)
        return (ret,)

    def deletes(self, nos):
        count = len(nos)
        delarray = (c_int * count)()
        for i in range(0, count):
            delarray[i] = nos[i]
        ret = tpi.TPI_Deletes(self.cur.hset, count, delarray)
        return (ret,)

    def edit(self):
        ret = tpi.TPI_Edit(self.cur.hset)
        return (ret,)

    def update(self, bunicode = False):
        ret = tpi.TPI_Update(self.cur.hset, bunicode)
        return (ret,)

    def cancelUpdate(self):
        ret = tpi.TPI_CancelUpdate(self.cur.hset)
        return (ret,)

    def setFieldValue(self, fieldsn, fieldvalue):
        buflen = len(fieldvalue)
        ret = tpi.TPI_SetFieldValue(self.cur.hset, fieldsn, fieldvalue, buflen)
        return (ret,)

    def setFieldValueByName(self, fieldname, fieldvalue):
        buflen = len(fieldvalue)
        ret = tpi.TPI_SetFieldValueByName(self.cur.hset, fieldname, fieldvalue, buflen)
        return (ret,)

    def getFieldValue(self, fieldsn):
        buflen = (tpi.TPI_GetColDataLen(self.conn.hcon, self.cur.hset, fieldsn) + 1) * sizeof(c_wchar)
        buf = create_unicode_buffer(buflen)
        ret = tpi.TPI_GetFieldValue(self.cur.hset, fieldsn, buf, buflen)
        if ret >= 0:
            try:
                return (ret, buf.value)
            except ValueError:
                pos = 0
                try:
                    for pos in range(buflen):
                        wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                except ValueError:
                    if 0 == pos:
                        return (ret, "")
                    pos = pos - 1
                    return (ret, wstring_at(buf, pos))
        else:
            return (ret,)

    def getFieldValueEx(self, fieldsn, flag = 0):
        buflen = c_int(0)
        buflen.value = (tpi.TPI_GetColDataLen(self.conn.hcon, self.cur.hset, fieldsn) + 1) * sizeof(c_wchar)
        buf = create_unicode_buffer(buflen.value)
        ret = tpi.TPI_GetFieldValueEx(self.cur.hset, fieldsn, buf, byref(buflen), flag)
        if ret >= 0:
            try:
                return (ret, buf.value)
            except ValueError:
                pos = 0
                try:
                    for pos in range(buflen.value):
                        wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                except ValueError:
                    if 0 == pos:
                        return (ret, "")
                    pos = pos - 1
                    return (ret, wstring_at(buf, pos))
        else:
            return (ret,)

    def getFieldValueByName(self, fieldname):
        buflen = (tpi.TPI_GetColDataLenByFieldName(self.conn.hcon, self.cur.hset, fieldname) + 1) * sizeof(c_wchar)
        buf = create_unicode_buffer(buflen)
        while True:
            ret = tpi.TPI_GetFieldValueByName(self.cur.hset, fieldname, buf, buflen)
            if ret == tpi.TPI_ERR_BUFFER:
                del (buf)
                buflen *= 2
                buf = create_unicode_buffer(buflen)
                continue
            elif ret >= 0:
                try:
                    return (ret, buf.value)
                except ValueError:
                    pos = 0
                    try:
                        for pos in range(buflen):
                            wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                    except ValueError:
                        if 0 == pos:
                            return (ret, "")
                        pos = pos - 1
                        return (ret, wstring_at(buf, pos))
            else:
                return (ret,)

    def getFieldValueByNameEx(self, fieldname, flag = 0):
        buflen = c_int(0)
        buflen.value = (tpi.TPI_GetColDataLenByFieldName(self.conn.hcon, self.cur.hset, fieldname) + 1) * sizeof(c_wchar)
        buf = create_unicode_buffer(buflen.value)
        while True:
            ret = tpi.TPI_GetFieldValueByNameEx(self.cur.hset, fieldname, buf, byref(buflen), flag)
            if ret == tpi.TPI_ERR_BUFFER:
                del (buf)
                buflen.value *= 2
                buf = create_unicode_buffer(buflen.value)
                continue
            elif ret >= 0:
                try:
                    return (ret, buf.value)
                except ValueError:
                    pos = 0
                    try:
                        for pos in range(buflen.value):
                            wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                    except ValueError:
                        if 0 == pos:
                            return (ret, "")
                        pos = pos - 1
                        return (ret, wstring_at(buf, pos))
            else:
                return (ret,)

    def getFieldLen(self, fieldsn):
        buflen = c_int(0)
        ret = tpi.TPI_GetFieldLen(self.cur.hset, fieldsn, byref(buflen))
        if ret >= 0:
            ret = buflen.value
        return (ret,)

    def getColDataLen(self, fieldsn):
        ret = tpi.TPI_GetColDataLen(self.conn.hcon, self.cur.hset, fieldsn)
        return (ret,)

    def getColDataLenEx(self, fieldsn, flag = 0):
        ret = tpi.TPI_GetColDataLenEx(self.conn.hcon, self.cur.hset, fieldsn, flag)
        return (ret,)

    def getColDataLenByFieldName(self, fieldname):
        ret = tpi.TPI_GetColDataLenByFieldName(self.conn.hcon, self.cur.hset, fieldname)
        return (ret,)

    def getColDataLenByFieldNameEx(self, fieldname, flag = 0):
        ret = tpi.TPI_GetColDataLenByFieldNameEx(self.conn.hcon, self.cur.hset, fieldname, flag)
        return (ret,)

    def getRecordTableName(self):
        tablename = create_unicode_buffer(tpi.TABLENAME_LENGTH)
        ret = tpi.TPI_GetRecordTableName(self.cur.hset, tablename)
        if ret >= 0:
            try:
                return (ret, tablename.value)
            except ValueError:
                pos = 0
                try:
                    for pos in range(tpi.TABLENAME_LENGTH):
                        wstring_at(byref(tablename, pos * sizeof(c_wchar)), 1)
                except ValueError:
                    if 0 == pos:
                        return (ret, "")
                    pos = pos - 1
                    return (ret, wstring_at(tablename, pos))
        else:
            return (ret,)

    def getFieldCount(self):
        ret = tpi.TPI_GetFieldCount(self.cur.hset)
        return (ret,)

    def getFieldInfo(self):
        fieldcount = tpi.TPI_GetFieldCount(self.cur.hset)
        fieldinfo = (tpi.HS_TABLE_FIELD * fieldcount)()
        ret = tpi.TPI_GetFieldInfo(self.cur.hset, fieldinfo)
        return (ret, fieldinfo)

    def getFieldName(self, fieldsn):
        fieldname = create_unicode_buffer(tpi.HS_FIELD_NAME_LEN)
        ret = tpi.TPI_GetFieldName(self.cur.hset, fieldsn, fieldname)
        if ret >= 0:
            try:
                return (ret, fieldname.value)
            except ValueError:
                pos = 0
                try:
                    for pos in range(tpi.HS_FIELD_NAME_LEN):
                        wstring_at(byref(fieldname, pos * sizeof(c_wchar)), 1)
                except ValueError:
                    if 0 == pos:
                        return (ret, "")
                    pos = pos - 1
                    return (ret, wstring_at(fieldname, pos))
        else:
            return (ret,)

    def getRecordSetFieldName(self, flag = 0):
        count = tpi.TPI_GetFieldCount(self.cur.hset)
        bufsize = c_int(count * tpi.HS_FIELD_NAME_LEN)
        fieldlist = create_unicode_buffer(bufsize.value)
        ret = tpi.TPI_GetRecordSetFieldName(self.cur.hset, fieldlist, byref(bufsize), flag)
        if ret >= 0:
            try:
                return (ret, fieldlist.value)
            except ValueError:
                pos = 0
                try:
                    for pos in range(bufsize.value):
                        wstring_at(byref(fieldlist, pos * sizeof(c_wchar)), 1)
                except ValueError:
                    if 0 == pos:
                        return (ret, "")
                    pos = pos - 1
                    return (ret, wstring_at(fieldlist, pos))
        else:
            return (ret,)

    def getFieldIndex(self, tablename, fieldname):
        ret = tpi.TPI_GetFieldIndex(self.conn.hcon, tablename, fieldname)
        return (ret,)

    def getFieldType(self, fieldsn):
        fieldtype = c_int(0)
        ret = tpi.TPI_GetFieldType(self.cur.hset, fieldsn, byref(fieldtype))
        if ret >= 0:
            ret = fieldtype.value
        return (ret,)

    def getFieldTypeByName(self, fieldname):
        ret = tpi.TPI_GetFieldTypeByName(self.cur.hset, fieldname)
        return (ret,)

    def getFieldEncodingByName(self, fieldname):
        ret = tpi.TPI_GetFieldEncodingByName(self.cur.hset, fieldname)
        return (ret,)

    def getTableHead(self):
        headinfo = (tpi.HS_TABLE_HEAD)()
        ret = tpi.TPI_GetTableHead(self.cur.hset, headinfo)
        return (ret, headinfo)

    def getTableSize(self):
        ret = tpi.TPI_GetTableSize(self.cur.hset)
        return (ret,)

    def getTablePath(self):
        tablepath = create_unicode_buffer(tpi.MAX_PATH)
        ret = tpi.TPI_GetTablePath(self.cur.hset, tablepath)
        if ret >= 0:
            try:
                return (ret, tablepath.value)
            except ValueError:
                pos = 0
                try:
                    for pos in range(tpi.MAX_PATH):
                        wstring_at(byref(tablepath, pos * sizeof(c_wchar)), 1)
                except ValueError:
                    if 0 == pos:
                        return (ret, "")
                    pos = pos - 1
                    return (ret, wstring_at(tablepath, pos))
        else:
            return (ret,)

    def createTable(self, tableinfo):
        ret = tpi.TPI_CreateTable(self.conn.hcon, tableinfo)
        return (ret, )

    def createTable2(self, tableinfo, dbname):
        ret = tpi.TPI_CreateTable2(self.conn.hcon, tableinfo, dbname)
        return (ret,)

    def deleteTable(self, tablename):
        ret = tpi.TPI_DeleteTable(self.conn.hcon, tablename)
        return (ret,)

    def modifyTable(self, tableinfo, modiitem, eventhandle = 0):
        count = len(modiitem)
        itemarray = (c_int * count)()
        for i in range(0, count):
            itemarray[i] = modiitem[i]
        ret = tpi.TPI_ModifyTable(self.conn.hcon, tableinfo, itemarray, eventhandle)
        return (ret,)

    def importTable(self, tablepath):
        ret = tpi.TPI_ImportTable(self.conn.hcon, tablepath)
        return (ret,)

    def packTable(self, tablename):
        ret = tpi.TPI_PackTable(self.conn.hcon, tablename)
        return (ret,)

    def indexTable(self, tablename, eventhandle = 0):
        ret = tpi.TPI_IndexTable(self.conn.hcon, tablename, eventhandle)
        return (ret,)

    def indexTableField(self, tablename, cols, eventhandle = 0):
        count = len(cols)
        colsarray = (c_int * count)()
        for i in range(0, count):
            colsarray[i] = cols[i]
        ret = tpi.TPI_IndexTableField(self.conn.hcon, tablename, colsarray, eventhandle)
        return (ret,)

    def optimizeTable(self, tablename, eventhandle = 0):
        ret = tpi.TPI_OptimizeTable(self.conn.hcon, tablename, eventhandle)
        return (ret,)

    def renameTable(self, tablename, aliasname = None, newname = None):
        ret = tpi.TPI_RenameTable(self.conn.hcon, tablename, aliasname, newname)
        return (ret,)

    def getSvrInfo(self):
        svrinfo = tpi.TPI_SERVER_SYSTEMINFO()
        ret = tpi.TPI_GetSvrInfo(self.conn.hcon, svrinfo)
        return (ret, svrinfo)

    def getServerInfo(self):
        serverinfo = tpi.TPI_SERVER_SYSTEMINFO_EX()
        size = c_int((sizeof(tpi.TPI_SERVER_SYSTEMINFO_EX)))
        ret = tpi.TPI_GetServerInfo(self.conn.hcon, serverinfo, size)
        return (ret, serverinfo)

    def getServerDiskInfo(self, diskcnt):
        diskinfo = (tpi.TPI_DISKINFO * diskcnt)()
        diskcount = c_int(diskcnt)
        ret = tpi.TPI_GetServerDiskInfo(self.conn.hcon, diskinfo, byref(diskcount))
        return (ret, diskinfo)

    def getServerDirCount(self, srcpath):
        ret = tpi.TPI_GetServerDirCount(self.conn.hcon, srcpath)
        return (ret,)

    def getServerDirList(self, path, startpos, count, dirflag = 0):
        dirinfo = (tpi.TPI_DIRINFO * count)()
        dircount = c_int(count)
        ret = tpi.TPI_GetServerDirList(self.conn.hcon, path, startpos, byref(dircount), dirflag, dirinfo)
        return (ret, dirinfo)

    def getServerPath(self):
        svrpath = create_unicode_buffer(tpi.MAX_PATH)
        ret = tpi.TPI_GetServerPath(self.conn.hcon, svrpath)
        if ret >= 0:
            try:
                return (ret, svrpath.value)
            except ValueError:
                pos = 0
                try:
                    for pos in range(tpi.MAX_PATH):
                        wstring_at(byref(svrpath, pos * sizeof(c_wchar)), 1)
                except ValueError:
                    if 0 == pos:
                        return (ret, "")
                    pos = pos - 1
                    return (ret, wstring_at(svrpath, pos))
        else:
            return (ret,)

    def copyFiles(self, copyfile):
        ret = tpi.TPI_CopyFiles(self.conn.hcon, copyfile)
        return (ret,)

    def deleteFiles(self, filename):
        ret = tpi.TPI_DeleteFiles(self.conn.hcon, filename)
        return (ret,)

    def fileExists(self, filename):
        ret = tpi.TPI_FileExists(self.conn.hcon, filename)
        return (ret,)

    def copyDir(self, copyfile):
        ret = tpi.TPI_CopyDir(self.conn.hcon, copyfile)
        return (ret,)

    def makeDir(self, dirpath):
        ret = tpi.TPI_MakeDir(self.conn.hcon, dirpath)
        return (ret,)

    def removeDir(self, dirpath):
        ret = tpi.TPI_RemoveDir(self.conn.hcon, dirpath)
        return (ret,)

    def readStruct(self, inirw):
        ret = tpi.TPI_ReadStruct(self.conn.hcon, inirw)
        return (ret, inirw)

    def writeStruct(self, inirw):
        ret = tpi.TPI_WriteStruct(self.conn.hcon, inirw)
        return (ret, inirw)

    def readString(self, inirw):
        ret = tpi.TPI_ReadString(self.conn.hcon, inirw)
        return (ret, inirw)

    def writeString(self, inirw):
        ret = tpi.TPI_WriteString(self.conn.hcon, inirw)
        return (ret, inirw)

    def appentRecText(self, tablename, packfile):
        ret = tpi.TPI_AppentRecText(self.conn.hcon, tablename, packfile)
        return (ret, )

    def addRecData(self, addrecinfo, bunicode = False):
        ret = tpi.TPI_AddRecData(self.conn.hcon, addrecinfo, bunicode)
        return (ret,)

    def appentStart(self, tablename):
        ret = tpi.TPI_AppentStart(self.conn.hcon, tablename)
        return (ret,)

    def appentTable(self, addrecinfo, bunicode = False):
        ret = tpi.TPI_AppentTable(self.conn.hcon, addrecinfo, bunicode)
        return (ret,)

    def appentEnd(self, tablename):
        ret = tpi.TPI_AppentEnd(self.conn.hcon, tablename)
        return (ret,)

    def readFile(self, srcfile, destfile):
        ret = tpi.TPI_ReadFile(self.conn.hcon, srcfile, destfile)
        return (ret,)

    def writeFile(self, srcfile, destfile):
        ret = tpi.TPI_WriteFile(self.conn.hcon, srcfile, destfile)
        return (ret,)

    def clearTableByName(self, tablename):
        ret = tpi.TPI_ClearTableByName(self.conn.hcon, tablename)
        return (ret,)

    def closeTable(self, tablename):
        ret = tpi.TPI_CloseTable(self.conn.hcon, tablename)
        return (ret,)

    def openTable(self, tablename):
        ret = tpi.TPI_OpenTable(self.conn.hcon, tablename)
        return (ret,)

    def bulkSetRecord(self, bulksetrec, col, data, bunicode = False):
        ret = tpi.TPI_BulkSetRecord(self.conn.hcon, bulksetrec, col, data, bunicode)
        return (ret,)

    def bulkSetRecordEx(self, bulksetrec, cols, data, bunicode = False):
        ret = tpi.TPI_BulkSetRecordEx(self.conn.hcon, bulksetrec, cols, data, bunicode)
        return (ret,)

    def lockQuery(self, lockflag):
        ret = tpi.TPI_LockQuery(self.conn.hcon, self.cur.hset,  lockflag)
        return (ret,)

    def wordSegment(self, srcbuf):
        size = c_int((len(srcbuf)+1)*4)
        destbuf = create_unicode_buffer(size.value)
        ret = tpi.TPI_WordSegment(self.conn.hcon, srcbuf, destbuf, byref(size))
        if ret >= 0:
            try:
                return (ret, destbuf.value)
            except ValueError:
                pos = 0
                try:
                    for pos in range(size.value):
                        wstring_at(byref(destbuf, pos * sizeof(c_wchar)), 1)
                except ValueError:
                    if 0 == pos:
                        return (ret, "")
                    pos = pos - 1
                    return (ret, wstring_at(destbuf, pos))
        else:
            return (ret,)

    def setRecordCount(self, count):
        ret = tpi.TPI_SetRecordCount(self.cur.hset, count)
        return (ret,)

    def clientCmd(self, cmd):
        size = c_int(2048)
        destbuf = create_unicode_buffer(size.value)
        ret = tpi.TPI_ClientCmd(self.conn.hcon, destbuf, byref(size), cmd)
        if ret >= 0:
            try:
                return (ret, destbuf.value)
            except ValueError:
                pos = 0
                try:
                    for pos in range(size.value):
                        wstring_at(byref(destbuf, pos * sizeof(c_wchar)), 1)
                except ValueError:
                    if 0 == pos:
                        return (ret, "")
                    pos = pos - 1
                    return (ret, wstring_at(destbuf, pos))
        else:
            return (ret,)

    def reloadDict(self, dictname):
        ret = tpi.TPI_ReloadDict(self.conn.hcon,dictname)
        return (ret,)

    def KEGetDicts(self):
        size = c_int(2048)
        xmldict = create_unicode_buffer(size.value)
        ret = tpi.TPI_KEGetDicts(self.conn.hcon, xmldict, byref(size))
        if ret >= 0:
            try:
                return (ret, xmldict.value)
            except ValueError:
                pos = 0
                try:
                    for pos in range(size.value):
                        wstring_at(byref(xmldict, pos * sizeof(c_wchar)), 1)
                except ValueError:
                    if 0 == pos:
                        return (ret, "")
                    pos = pos - 1
                    return (ret, wstring_at(xmldict, pos))
        else:
            return (ret,)

    def getFieldTypeNameBySN(self, fieldno):
        fieldname = create_unicode_buffer(tpi.HS_FIELD_NAME_LEN)
        ret = tpi.TPI_GetFieldTypeNameBySN(fieldno, fieldname)
        if ret >= 0:
            try:
                return (ret, fieldname.value)
            except ValueError:
                pos = 0
                try:
                    for pos in range(tpi.HS_FIELD_NAME_LEN):
                        wstring_at(byref(fieldname, pos * sizeof(c_wchar)), 1)
                except ValueError:
                    if 0 == pos:
                        return (ret, "")
                    pos = pos - 1
                    return (ret, wstring_at(fieldname, pos))
        else:
            return (ret,)

    def getSNByFieldTypeName(self, fieldname):
        ret = tpi.TPI_GetSNByFieldTypeName(fieldname)
        return (ret,)

    def getIndexTypeNameBySN(self, indexno):
        indexname = create_unicode_buffer(tpi.HS_FIELD_NAME_LEN)
        ret = tpi.TPI_GetIndexTypeNameBySN(indexno, indexname)
        if ret >= 0:
            try:
                return (ret, indexname.value)
            except ValueError:
                pos = 0
                try:
                    for pos in range(tpi.HS_FIELD_NAME_LEN):
                        wstring_at(byref(indexname, pos * sizeof(c_wchar)), 1)
                except ValueError:
                    if 0 == pos:
                        return (ret, "")
                    pos = pos - 1
                    return (ret, wstring_at(indexname, pos))
        else:
            return (ret,)

    def getSNByIndexTypeName(self, indexname):
        ret = tpi.TPI_GetSNByIndexTypeName(indexname)
        return (ret,)

    def USPSetReplaceUrl(self, url):
        ret = tpi.TPI_USPSetReplaceUrl(self.conn.hcon, url)
        return (ret,)

    def USPUrlGetContent(self, tablename, search, resultid, urlid, type, offset, buf, buflen = None):
        ret = tpi.TPI_USPUrlGetContent(self.conn.hcon, tablename, search, resultid, urlid, type, offset, buf, buflen)
        return (ret,)

    def getRelevantWords(self, keyword, wordnum, seperatorchar, wordfreqfollowed, dbname = 'sys_dict_relevant'):
        size = c_int(4096)
        releventwords = create_unicode_buffer(size.value)
        sepchar = ord(seperatorchar)
        while True:
            ret = tpi.TPI_GetRelevantWords(self.conn.hcon, keyword, releventwords, size.value, wordnum, sepchar, wordfreqfollowed, dbname)
            if ret == tpi.TPI_ERR_BUFFER:
                del (releventwords)
                size.value *= 2
                releventwords = create_unicode_buffer(size.value)
                continue
            elif ret >= 0:
                try:
                    return (ret, releventwords.value)
                except ValueError:
                    pos = 0
                    try:
                        for pos in range(size.value):
                            wstring_at(byref(releventwords, pos * sizeof(c_wchar)), 1)
                    except ValueError:
                        if 0 == pos:
                            return (ret, "")
                        pos = pos - 1
                        return (ret, wstring_at(releventwords, pos))
            else:
                return (ret,)

    def getRecordRelevant(self):
        ret = tpi.TPI_GetRecordRelevant(self.conn.hcon, self.cur.hset)
        return (ret,)

    def getQuerySQL(self, bunicode = False):
        size = c_int(1024)
        ksql = create_unicode_buffer(size.value)
        ret = tpi.TPI_GetQuerySQL(self.conn.hcon, self.cur.hset, ksql, byref(size), bunicode)
        if ret >= 0:
            try:
                return (ret, ksql.value)
            except ValueError:
                pos = 0
                try:
                    for pos in range(size.value):
                        wstring_at(byref(ksql, pos * sizeof(c_wchar)), 1)
                except ValueError:
                    if 0 == pos:
                        return (ret, "")
                    pos = pos - 1
                    return (ret, wstring_at(ksql, pos))
        else:
            return (ret,)

    def TM_SimSearch(self, ksql, vsm, field = 'word_vsm', bunicode = False):
        errcode = c_int(0)
        hset = tpi.TPI_TM_SimSearch(self.conn.hcon, ksql, vsm, byref(errcode), field, bunicode)
        ret = errcode.value
        if ret >= 0:
            cur = cursor()
            cur.conn = self.conn
            cur.hset = hset
            cur.opend = 1
            cur.colcount = tpi.TPI_GetFieldCount(hset)
            cur.rowcount = tpi.TPI_GetRecordSetCount(hset)
            return (errcode.value, cur)
        else:
            return (ret,)

    def TM_LoadDict(self, dicttable):
        ret = tpi.TPI_TM_LoadDict(self.conn.hcon, dicttable)
        return (ret,)

    def TM_UnLoadDict(self, dicthandle):
        ret = tpi.TPI_TM_UnLoadDict(self.conn.hcon, dicthandle)
        return (ret,)

    def TM_GetDictHandle(self, dicttable):
        ret = tpi.TPI_TM_GetDictHandle(self.conn.hcon, dicttable)
        return (ret,)

    def TM_DeleteDictHandle(self, dicthandle):
        ret = tpi.TPI_TM_DeleteDictHandle(self.conn.hcon, dicthandle)
        return (ret,)

    def getTableHandle(self):
        ret = tpi.TPI_GetTableHandle(self.cur.hset)
        return (ret,)

    def getTableType(self, htable):
        ret = tpi.TPI_GetTableType(self.conn.hcon, htable)
        return (ret,)

    def getTableHitCount(self, tablename):
        ret = tpi.TPI_GetTableHitCount(self.cur.hset, tablename)
        return (ret,)

    def getTableHostIP(self, htable):
        size = c_int(32)
        ip = create_unicode_buffer(size.value)
        ret = tpi.TPI_GetTableHostIP(self.conn.hcon, htable, ip, byref(size))
        if ret >= 0:
            try:
                return (ret, ip.value)
            except ValueError:
                pos = 0
                try:
                    for pos in range(size.value):
                        wstring_at(byref(ip, pos * sizeof(c_wchar)), 1)
                except ValueError:
                    if 0 == pos:
                        return (ret, "")
                    pos = pos - 1
                    return (ret, wstring_at(ip, pos))
        else:
            return (ret, )

    def getDatabaseCount(self):
        ret = tpi.TPI_GetDatabaseCount(self.conn.hcon)
        return (ret,)

    def getDatabaseName(self, dbindex):
        size = tpi.HS_TABLE_NAME_LEN
        buf = create_unicode_buffer(size)
        ret = tpi.TPI_GetDatabaseName(self.conn.hcon, dbindex, buf, size)
        if ret >= 0:
            try:
                return (ret, buf.value)
            except ValueError:
                pos = 0
                try:
                    for pos in range(size):
                        wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                except ValueError:
                    if 0 == pos:
                        return (ret, "")
                    pos = pos - 1
                    return (ret, wstring_at(buf, pos))
        else:
            return (ret,)

    def getAllDatabaseName(self):
        count = self.getDatabaseCount()
        size = count[0] * tpi.HS_TABLE_NAME_LEN
        buf = create_unicode_buffer(size)
        ret = tpi.TPI_GetAllDatabaseName(self.conn.hcon, buf, size)
        if ret >= 0:
            try:
                return (ret, buf.value)
            except ValueError:
                pos = 0
                try:
                    for pos in range(size):
                        wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                except ValueError:
                    if 0 == pos:
                        return (ret, "")
                    pos = pos - 1
                    return (ret, wstring_at(buf, pos))
        else:
            return (ret,)
        pass

    def getTablesListInDB(self, dbname):
        size = c_int(4096)
        buf = create_unicode_buffer(size.value)
        while True:
            ret = tpi.TPI_GetTablesListInDB(self.conn.hcon, dbname, buf, size)
            if ret == tpi.TPI_ERR_BUFFER:
                del(buf)
                size.value *= 2
                buf = create_unicode_buffer(size.value)
                continue
            elif ret >= 0:
                try:
                    return (ret, buf.value)
                except ValueError:
                    pos = 0
                    try:
                        for pos in range(size.value):
                            wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                    except ValueError:
                        if 0 == pos:
                            return (ret, "")
                        pos = pos - 1
                        return (ret, wstring_at(buf, pos))
            else:
                return (ret,)

    def getTableInfoFromCache(self, tablename):
        info = tpi.TPI_TABLE_INFO()
        size = 0
        ret = tpi.TPI_GetTableInfoFromCache(self.conn.hcon, tablename, info, size)
        if ret >= 0:
            return (ret, info)
        else:
            return (ret,)

    def getViewIndex(self, viewname):
        ret = tpi.TPI_GetViewIndex(self.conn.hcon, viewname)
        return (ret,)

    def getFieldTypeList(self):
        size = c_int(4096)
        buf = create_unicode_buffer(size.value)
        while True:
            ret = tpi.TPI_GetFieldTypeList(buf, size)
            if ret == tpi.TPI_ERR_BUFFER:
                del(buf)
                size.value *= 2
                buf = create_unicode_buffer(size.value)
                continue
            elif ret >= 0:
                try:
                    return (ret, buf.value)
                except ValueError:
                    pos = 0
                    try:
                        for pos in range(size.value):
                            wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                    except ValueError:
                        if 0 == pos:
                            return (ret, "")
                        pos = pos - 1
                        return (ret, wstring_at(buf, pos))
            else:
                return (ret,)

    def getIndexTypeList(self):
        size = c_int(4096)
        buf = create_unicode_buffer(size.value)
        while True:
            ret = tpi.TPI_GetIndexTypeList(buf, size)
            if ret == tpi.TPI_ERR_BUFFER:
                del(buf)
                size.value *= 2
                buf = create_unicode_buffer(size.value)
                continue
            elif ret >= 0:
                try:
                    return (ret, buf.value)
                except ValueError:
                    pos = 0
                    try:
                        for pos in range(size.value):
                            wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                    except ValueError:
                        if 0 == pos:
                            return (ret, "")
                        pos = pos - 1
                        return (ret, wstring_at(buf, pos))
            else:
                return (ret,)

    def getAllTableType(self):
        size = c_int(4096)
        buf = create_unicode_buffer(size.value)
        while True:
            ret = tpi.TPI_GetAllTableType(self.conn.hcon, buf, size)
            if ret == tpi.TPI_ERR_BUFFER:
                del(buf)
                size.value *= 2
                buf = create_unicode_buffer(size.value)
                continue
            elif ret >= 0:
                try:
                    return (ret, buf.value)
                except ValueError:
                    pos = 0
                    try:
                        for pos in range(size.value):
                            wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                    except ValueError:
                        if 0 == pos:
                            return (ret, "")
                        pos = pos - 1
                        return (ret, wstring_at(buf, pos))
            else:
                return (ret,)

    def getSysDbList(self):
        size = c_int(4096)
        buf = create_unicode_buffer(size.value)
        while True:
            ret = tpi.TPI_GetSysDbList(self.conn.hcon, buf, size)
            if ret == tpi.TPI_ERR_BUFFER:
                del(buf)
                size.value *= 2
                buf = create_unicode_buffer(size.value)
                continue
            elif ret >= 0:
                try:
                    return (ret, buf.value)
                except ValueError:
                    pos = 0
                    try:
                        for pos in range(size.value):
                            wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                    except ValueError:
                        if 0 == pos:
                            return (ret, "")
                        pos = pos - 1
                        return (ret, wstring_at(buf, pos))
            else:
                return (ret,)

    def queryEvent(self, hevent):
        ret = tpi.TPI_QueryEvent(self.conn.hcon, hevent)
        return (ret,)

    def getTableHandle2(self, tablename):
        ret = tpi.TPI_GetTableHandle2(self.conn.hcon, tablename)
        return (ret,)

    def getDBNameofTable(self, tablename):
        size = c_int(tpi.HS_TABLE_NAME_LEN)
        dbname = create_unicode_buffer(size.value)
        ret = tpi.TPI_GetDBNameofTable(self.conn.hcon, tablename, dbname, size)
        if ret >= 0:
            try:
                return (ret, dbname.value)
            except ValueError:
                pos = 0
                try:
                    for pos in range(size.value):
                        wstring_at(byref(dbname, pos * sizeof(c_wchar)), 1)
                except ValueError:
                    if 0 == pos:
                        return (ret, "")
                    pos = pos - 1
                    return (ret, wstring_at(dbname, pos))
        else:
            return (ret,)

    def getDBRight(self, info):
        rightmode = c_int(0)
        ret = tpi.TPI_GetDBRight(self.conn.hcon, info, rightmode)
        if ret >= 0:
            ret = rightmode.value
        return (ret,)

    def getDBField(self, ad):
        size = c_int(4096)
        buf = create_unicode_buffer(size.value)
        while True:
            ret = tpi.TPI_GetDBField(self.conn.hcon, buf, size, ad)
            if ret == tpi.TPI_ERR_BUFFER:
                del(buf)
                size.value *= 2
                buf = create_unicode_buffer(size.value)
                continue
            elif ret >= 0:
                try:
                    return (ret, buf.value)
                except ValueError:
                    pos = 0
                    try:
                        for pos in range(size.value):
                            wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                    except ValueError:
                        if 0 == pos:
                            return (ret, "")
                        pos = pos - 1
                        return (ret, wstring_at(buf, pos))
            else:
                return (ret,)

    def createView(self, viewname, sql, modify, bunicode = False):
        ret = tpi.TPI_CreateView(self.conn.hcon, viewname, sql, modify, bunicode)
        return (ret,)

    def deleteView(self, viewname):
        ret = tpi.TPI_DeleteView(self.conn.hcon, viewname)
        return (ret,)

    def getTableCountEx(self, type):
        ret = tpi.TPI_GetTableCountEx(self.conn.hcon, type)
        return (ret,)

    def getTablesQueryInDB(self, dbname):
        cur = cursor()
        errcode = c_int(0)
        hset = tpi.TPI_GetTablesQueryInDB(self.conn.hcon, dbname, errcode)
        if errcode.value >= 0:
            cur.conn = self.conn
            cur.hset = hset
            cur.opend = 1
            cur.colcount = tpi.TPI_GetFieldCount(hset)
            cur.rowcount = tpi.TPI_GetRecordSetCount(hset)
            return (errcode.value, cur)
        else:
            return (errcode.value,)

    def getTableNameEx(self, tableindex, type):
        size = c_int(4096)
        buf = create_unicode_buffer(size.value)
        while True:
            ret = tpi.TPI_GetTableNameEx(self.conn.hcon, tableindex, type, buf, size)
            if ret == tpi.TPI_ERR_BUFFER:
                del (buf)
                size.value *= 2
                buf = create_unicode_buffer(size.value)
                continue
            elif ret >= 0:
                try:
                    return (ret, buf.value)
                except ValueError:
                    pos = 0
                    try:
                        for pos in range(size.value):
                            wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                    except ValueError:
                        if 0 == pos:
                            return (ret, "")
                        pos = pos - 1
                        return (ret, wstring_at(buf, pos))
            else:
                return (ret,)

    def getTablesFieldsList(self):
        ret = tpi.TPI_GetTablesFieldsList(self.conn.hcon)
        if ret >= 0:
            cur = self.cur
            return (ret, cur)
        else:
            return (ret,)

    def refreshTableInfo(self, tablename):
        ret = tpi.TPI_RefreshTableInfo(self.conn.hcon, tablename)
        return (ret,)

    def importTable2(self, path, dbname):
        ret = tpi.TPI_ImportTable2(self.conn.hcon, path, dbname)
        return (ret,)

    def moveTable(self, tablename, dbname):
        ret = tpi.TPI_MoveTable(self.conn.hcon, tablename, dbname)
        return (ret,)

    def getBLob(self, colno, offset, nread):
        buf = create_string_buffer(nread)
        ret = tpi.TPI_GetBLob(self.cur.hset, colno, 0, offset, buf, nread)
        if ret >= 0:
            return (ret, buf.value)
        else:
            return (ret,)

    def setBLob(self, colno, type, binaryseries):
        size = len(binaryseries)
        ret = tpi.TPI_SetBLob(self.cur.hset, colno, 0, type, binaryseries, size)
        return (ret,)

    def isEndPage(self):
        ret = tpi.TPI_IsEndPage(self.cur.hset)
        return (ret,)

    def isSingleTableMode(self):
        ret = tpi.TPI_IsSingleTableMode(self.cur.hset)
        return (ret,)

    def createDataBase(self, dbname):
        ret = tpi.TPI_CreateDataBase(self.conn.hcon, dbname)
        return (ret,)

    def getTablesListInDBEx(self, dbname, listtype = 0):
        size = c_int(4096)
        buf = create_unicode_buffer(size.value)
        while True:
            ret = tpi.TPI_GetTablesListInDBEx(self.conn.hcon, dbname, buf, size, listtype)
            if ret == tpi.TPI_ERR_BUFFER:
                del (buf)
                size.value *= 2
                buf = create_unicode_buffer(size.value)
                continue
            elif ret >= 0:
                try:
                    return (ret, buf.value)
                except ValueError:
                    pos = 0
                    try:
                        for pos in range(size.value):
                            wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                    except ValueError:
                        if 0 == pos:
                            return (ret, "")
                        pos = pos - 1
                        return (ret, wstring_at(buf, pos))
            else:
                return (ret,)

    def setCacheFields(self, fieldlst):
        ret = tpi.TPI_SetCacheFields(self.cur.hset, fieldlst)
        return (ret,)

    def getCacheFields(self):
        size = c_int(4096)
        buf = create_unicode_buffer(size.value)
        while True:
            ret = tpi.TPI_GetCacheFields(self.cur.hset, buf, size)
            if ret == tpi.TPI_ERR_BUFFER:
                del (buf)
                size.value *= 2
                buf = create_unicode_buffer(size.value)
                continue
            elif ret >= 0:
                try:
                    return (ret, buf.value)
                except ValueError:
                    pos = 0
                    try:
                        for pos in range(size.value):
                            wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                    except ValueError:
                        if 0 == pos:
                            return (ret, "")
                        pos = pos - 1
                        return (ret, wstring_at(buf, pos))
            else:
                return (ret,)

    def refreshVQDataSet(self):
        ret = tpi.TPI_RefreshVQDataSet(self.cur.hset)
        return (ret,)

    def getVQRecordCount(self):
        ret = tpi.TPI_GetVQRecordCount(self.cur.hset)
        return (ret,)

    def getVQRecordCountByName(self, dbname):
        ret = tpi.TPI_GetVQRecordCountByName(self.cur.hset, dbname)
        return (ret,)

    def getVQMaxRecordCount(self):
        ret = tpi.TPI_GetVQMaxRecordCount(self.cur.hset)
        return (ret,)

    def VQExpandTo(self, rowno):
        ret = tpi.TPI_VQExpandTo(self.cur.hset, rowno)
        return (ret,)

    def getUserOfGroup(self, groupname):
        size = c_int(4096)
        buf = create_unicode_buffer(size.value)
        while True:
            ret = tpi.TPI_GetUserOfGroup(self.conn.hcon, buf, size, groupname)
            if ret == tpi.TPI_ERR_BUFFER:
                del (buf)
                size.value *= 2
                buf = create_unicode_buffer(size.value)
                continue
            elif ret >= 0:
                try:
                    return (ret, buf.value)
                except ValueError:
                    pos = 0
                    try:
                        for pos in range(size.value):
                            wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                    except ValueError:
                        if 0 == pos:
                            return (ret, "")
                        pos = pos - 1
                        return (ret, wstring_at(buf, pos))
            else:
                return (ret,)

    def getGroupOfUser(self, username):
        size = c_int(4096)
        buf = create_unicode_buffer(size.value)
        while True:
            ret = tpi.TPI_GetGroupOfUser(self.conn.hcon, buf, size, username)
            if ret == tpi.TPI_ERR_BUFFER:
                del (buf)
                size.value *= 2
                buf = create_unicode_buffer(size.value)
                continue
            elif ret >= 0:
                try:
                    return (ret, buf.value)
                except ValueError:
                    pos = 0
                    try:
                        for pos in range(size.value):
                            wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                    except ValueError:
                        if 0 == pos:
                            return (ret, "")
                        pos = pos - 1
                        return (ret, wstring_at(buf, pos))
            else:
                return (ret,)

    def outputRecToText(self, recinfo, fieldlst, bunicode = False):
        fieldlstlen = len(fieldlst)*2
        ret = tpi.TPI_OutputRecToText(self.conn.hcon, recinfo, fieldlst, fieldlstlen, bunicode)
        return (ret,)

    def createUnionTable(self, uniontablename, maintablename, subtables, uniontabledbname):
        ret = tpi.TPI_CreateUnionTable(self.conn.hcon, uniontablename, maintablename, subtables, uniontabledbname)
        return (ret,)

    def getUnionTableInfo(self, uniontablename):
        size = 4096
        buf = create_unicode_buffer(size)
        while True:
            ret = tpi.TPI_GetUnionTableInfo(self.conn.hcon, uniontablename, buf, size)
            if ret == tpi.TPI_ERR_BUFFER:
                del (buf)
                size *= 2
                buf = create_unicode_buffer(size)
                continue
            elif ret >= 0:
                try:
                    return (ret, buf.value)
                except ValueError:
                    pos = 0
                    try:
                        for pos in range(size):
                            wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                    except ValueError:
                        if 0 == pos:
                            return (ret, "")
                        pos = pos - 1
                        return (ret, wstring_at(buf, pos))
            else:
                return (ret,)

    def isRecordSetReadOnly(self):
        ret = tpi.TPI_IsRecordSetReadOnly(self.cur.hset)
        return (ret,)

    def reIndexTable(self, htable, startrec = 0):
        ret = tpi.TPI_ReIndexTable(self.conn.hcon, htable, startrec)
        return (ret,)

    def getFieldValueByXml(self, startrec, endtrec, flag, fieldlst, contentlen, bunicode = False):
        size = c_int(4096)
        buf = create_unicode_buffer(size.value)
        while True:
            ret = tpi.TPI_GetFieldValueByXml(self.cur.hset, startrec, endtrec, flag, fieldlst, contentlen, buf, size, bunicode)
            if ret == tpi.TPI_ERR_BUFFER:
                del (buf)
                size.value *= 2
                buf = create_unicode_buffer(size.value)
                continue
            elif ret >= 0:
                try:
                    return (ret, buf.value)
                except ValueError:
                    pos = 0
                    try:
                        for pos in range(size.value):
                            wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                    except ValueError:
                        if 0 == pos:
                            return (ret, "")
                        pos = pos - 1
                        return (ret, wstring_at(buf, pos))
            else:
                return (ret,)

    def getXmlRecordByMultiSQL(self, sqls, count, prefix, postfix, bunicode = False):
        size = c_int(4096)
        buf = create_unicode_buffer(size.value)
        while True:
            ret = tpi.TPI_GetXmlRecordByMultiSQL(self.conn.hcon, sqls, buf, size, count, prefix, postfix, bunicode)
            if ret == tpi.TPI_ERR_BUFFER:
                del (buf)
                size.value *= 2
                buf = create_unicode_buffer(size.value)
                continue
            elif ret >= 0:
                try:
                    return (ret, buf.value)
                except ValueError:
                    pos = 0
                    try:
                        for pos in range(size.value):
                            wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                    except ValueError:
                        if 0 == pos:
                            return (ret, "")
                        pos = pos - 1
                        return (ret, wstring_at(buf, pos))
            else:
                return (ret,)

    def clusterGetActiveNodes(self):
        size = c_int(4096)
        buf = create_unicode_buffer(size.value)
        while True:
            ret = tpi.TPI_Cluster_GetActiveNodes(self.conn.hcon, buf, size)
            if ret == tpi.TPI_ERR_BUFFER:
                del (buf)
                size.value *= 2
                buf = create_unicode_buffer(size.value)
                continue
            elif ret >= 0:
                try:
                    return (ret, buf.value)
                except ValueError:
                    pos = 0
                    try:
                        for pos in range(size.value):
                            wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                    except ValueError:
                        if 0 == pos:
                            return (ret, "")
                        pos = pos - 1
                        return (ret, wstring_at(buf, pos))
            else:
                return (ret,)

    def getCommunicationHandle(self):
        hftscon = 0
        ret = tpi.TPI_GetCommunicationHandle(self.conn.hcon, hftscon)
        return (ret,)

    def getRowNativeId(self, rowno):
        ret = tpi.TPI_GetRowNativeId(self.cur.hset, rowno)
        return (ret,)

    def getStorageSpaceName(self, tablename):
        size = c_int(4096)
        buf = create_unicode_buffer(size.value)
        while True:
            ret = tpi.TPI_GetStorageSpaceName(self.conn.hcon, tablename, buf, size)
            if ret == tpi.TPI_ERR_BUFFER:
                del (buf)
                size.value *= 2
                buf = create_unicode_buffer(size.value)
                continue
            elif ret >= 0:
                try:
                    return (ret, buf.value)
                except ValueError:
                    pos = 0
                    try:
                        for pos in range(size.value):
                            wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                    except ValueError:
                        if 0 == pos:
                            return (ret, "")
                        pos = pos - 1
                        return (ret, wstring_at(buf, pos))
            else:
                return (ret,)

    def getHotStarConfigParam(self):
        param = tpi.CONFIG_PARAM()
        ret = tpi.TPI_GetHotStarConfigParam(self.conn.hcon, param)
        if ret >= 0:
            return (ret, param)
        else:
            return (ret,)

    def setHotStarConfigParam(self, params):
        ret = tpi.TPI_SetHotStarConfigParam(self.conn.hcon, params)
        return (ret, )

    def sessionAccess(self, tablename):
        ret = tpi.TPI_SessionAccess(self.conn.hcon, tablename)
        return (ret,)

    def getIndexSpaceName(self, tablename):
        size = c_int(4096)
        buf = create_unicode_buffer(size.value)
        while True:
            ret = tpi.TPI_GetIndexSpaceName(self.conn.hcon, tablename, buf, size)
            if ret == tpi.TPI_ERR_BUFFER:
                del (buf)
                size.value *= 2
                buf = create_unicode_buffer(size.value)
                continue
            elif ret >= 0:
                try:
                    return (ret, buf.value)
                except ValueError:
                    pos = 0
                    try:
                        for pos in range(size.value):
                            wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                    except ValueError:
                        if 0 == pos:
                            return (ret, "")
                        pos = pos - 1
                        return (ret, wstring_at(buf, pos))
            else:
                return (ret,)

    def grantAllDBField(self, ads):
        count = len(ads)
        bufsize = 0
        ret = tpi.TPI_GrantAllDBField(self.conn.hcon, ads, bufsize, count)
        return (ret,)

    def grantAllDBRight(self, ads):
        count = len(ads)
        bufsize = 0
        ret = tpi.TPI_GrantAllDBRight(self.conn.hcon, ads, bufsize, count)
        return (ret,)

    def getStorageSpaceInfo(self, tablename, storagespacename):
        spaceinfo = tpi.TPI_TABLE_STORAGESPACE()
        size = 0
        ret = tpi.TPI_GetStorageSpaceInfo(self.conn.hcon, tablename, storagespacename, spaceinfo, size)
        if ret >= 0:
            return (ret, spaceinfo)
        else:
            return (ret,)

    def validateDBField(self, ads, fieldlst):
        ret = tpi.TPI_ValidateDBField(self.conn.hcon, ads, fieldlst)
        return (ret,)

    def validateDBRight(self, ads, rightmode):
        ret = tpi.TPI_ValidateDBRight(self.conn.hcon, ads, rightmode)
        return (ret,)

    def setFieldMap(self, tablename, mapiteminfos):
        count = len(mapiteminfos)
        mapitemarray = (tpi.HS_FIELD_MAP_ITEM * count)()
        for i in range(0, count):
            mapitemarray[i] = mapiteminfos[i]
        ret = tpi.TPI_SetFieldMap(self.conn.hcon, tablename, count, mapitemarray)
        return (ret,)

    def getFieldMap(self, tablename):
        mapcount = c_int(100)
        while True:
            mapiteminfos = (tpi.HS_FIELD_MAP_ITEM * mapcount.value)()
            ret = tpi.TPI_GetFieldMap(self.conn.hcon, tablename, mapcount, mapiteminfos)
            if ret == tpi.TPI_ERR_BUFFER:
                mapcount.value *= 2
                del (mapiteminfos)
                continue
            elif ret >= 0:
                return (ret, mapiteminfos)
            else:
                return (ret,)

    def predictRelevantConcept(self, keyword, recount, clusteridfollowed = False, dbname = tpi.SYS_CONCEPT_DIC, sep = '$'):
        size = c_int(4096)
        buf = create_unicode_buffer(size.value)
        while True:
            ret = tpi.TPI_PredictRelevantConcept(self.conn.hcon, keyword, recount, buf, size, clusteridfollowed, dbname, sep)
            if ret == tpi.TPI_ERR_BUFFER:
                del (buf)
                size.value *= 2
                buf = create_unicode_buffer(size.value)
                continue
            elif ret >= 0:
                try:
                    return (ret, buf.value)
                except ValueError:
                    pos = 0
                    try:
                        for pos in range(size.value):
                            wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                    except ValueError:
                        if 0 == pos:
                            return (ret, "")
                        pos = pos - 1
                        return (ret, wstring_at(buf, pos))
            else:
                return (ret,)

    def usp_Connect(self, ip, port, username, passwd):
        ret = tpi.TPI_USP_Connect(self.conn.hcon, ip, port, username, passwd)
        return (ret,)

    def usp_GetTableCount(self, huspcon):
        ret = tpi.TPI_USP_GetTableCount(self.conn.hcon, huspcon)
        return (ret,)

    def usp_GetTableName(self, huspcon, tableno):
        tablenamelen = c_int(tpi.TABLENAME_LENGTH)
        tablename = create_unicode_buffer(tablenamelen.value)
        ret = tpi.TPI_USP_GetTableName(self.conn.hcon, huspcon, tableno, tablename, tablenamelen)
        if ret >= 0:
            try:
                return (ret, tablename.value)
            except ValueError:
                pos = 0
                try:
                    for pos in range(tablenamelen.value):
                        wstring_at(byref(tablename, pos * sizeof(c_wchar)), 1)
                except ValueError:
                    if 0 == pos:
                        return (ret, "")
                    pos = pos - 1
                    return (ret, wstring_at(tablename, pos))
        else:
            return (ret,)

    def usp_GetFieldInfo(self, huspcon, tablename):
        fieldinfo = tpi.USP_FIELDINFO_RET()
        size = 0
        ret = tpi.TPI_USP_GetFieldInfo(self.conn.hcon, huspcon, tablename, fieldinfo, size)
        if ret >= 0:
            return (ret, fieldinfo)
        else:
            return (ret,)

    def usp_IsTableExist(self, huspcon, tablename):
        ret = tpi.TPI_USP_IsTableExist(self.conn.hcon, huspcon, tablename)
        return (ret,)

    def usp_ConTable(self, savepath, tablename, ip, port, conname, conpassword, dbname = 'USP'):
        ret = tpi.TPI_USP_ConTable(self.conn.hcon, savepath, tablename, ip, port, conname, conpassword, dbname)
        return (ret,)

    def usp_GetColInfo(self, huspcon, tablename):
        fieldnum = 100
        size = c_int(0)
        while True:
            fieldinfo = (tpi.HS_TABLE_FIELD * fieldnum)()
            size.value = sizeof(tpi.HS_TABLE_FIELD) * fieldnum
            ret = tpi.TPI_USP_GetColInfo(self.conn.hcon, huspcon, tablename, fieldinfo, size)
            if ret == tpi.TPI_ERR_BUFFER:
                fieldnum *= 2
                del(fieldinfo)
                continue
            elif ret >= 0:
                return (ret, fieldinfo)
            else:
                return (ret,)

    def tableReConHost(self, htable, ip, port, username, passwd):
        ret = tpi.TPI_TableReConHost(self.conn.hcon, htable, ip, port, username, passwd)
        return (ret,)

    def normalizeInput(self, inputstring, tf):
        size = c_int(4096)
        buf = create_unicode_buffer(size.value)
        while True:
            ret = tpi.TPI_NormalizeInput(inputstring, tf, buf, size)
            if ret == tpi.TPI_ERR_BUFFER:
                del (buf)
                size.value *= 2
                buf = create_unicode_buffer(size.value)
                continue
            elif ret >= 0:
                try:
                    return (ret, buf.value)
                except ValueError:
                    pos = 0
                    try:
                        for pos in range(size.value):
                            wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                    except ValueError:
                        if 0 == pos:
                            return (ret, "")
                        pos = pos - 1
                        return (ret, wstring_at(buf, pos))
            else:
                return (ret,)

    def normalizeInputForSE(self, inputstring, tf):
        size = c_int(4096)
        buf = create_unicode_buffer(size.value)
        while True:
            ret = tpi.TPI_NormalizeInputForSE(inputstring, tf, buf, size)
            if ret == tpi.TPI_ERR_BUFFER:
                del (buf)
                size.value *= 2
                buf = create_unicode_buffer(size.value)
                continue
            elif ret >= 0:
                try:
                    return (ret, buf.value)
                except ValueError:
                    pos = 0
                    try:
                        for pos in range(size.value):
                            wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                    except ValueError:
                        if 0 == pos:
                            return (ret, "")
                        pos = pos - 1
                        return (ret, wstring_at(buf, pos))
            else:
                return (ret,)

    def getIndexSpaceCol(self, tablename, indexspacename):
        size = c_int(4096)
        buf = create_unicode_buffer(size.value)
        while True:
            ret = tpi.TPI_GetIndexSpaceCol(self.conn.hcon, tablename, indexspacename, buf, size)
            if ret == tpi.TPI_ERR_BUFFER:
                del (buf)
                size.value *= 2
                buf = create_unicode_buffer(size.value)
                continue
            elif ret >= 0:
                try:
                    return (ret, buf.value)
                except ValueError:
                    pos = 0
                    try:
                        for pos in range(size.value):
                            wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                    except ValueError:
                        if 0 == pos:
                            return (ret, "")
                        pos = pos - 1
                        return (ret, wstring_at(buf, pos))
            else:
                return (ret,)

    def randomSubSetQuery(self, idseries):
        idnum = len(idseries)
        hrandomset = 0
        idarray = (c_int * idnum)()
        for i in range(0, idnum):
            idarray[i] = idseries[i]
        ret = tpi.TPI_RandomSubSetQuery(self.conn.hcon, self.cur.hset, idarray, idnum, hrandomset)
        return (ret,)

    def refreshCluster(self, reload):
        ret = tpi.TPI_RefreshCluster(reload)
        return (ret,)

    def createZ3950Table(self, tableinfo, tablehead, dbname):
        ret = tpi.TPI_CreateZ3950Table(self.conn.hcon, tableinfo, tablehead, dbname)
        return (ret,)

    def setRemoteCluster(self, ip, port, tablename):
        ret = tpi.TPI_SetRemoteCluster(ip, port, tablename)
        return (ret,)

    def setEvent(self, info, cmdcode, subcmdcode, param1, param1len, param2, param2len):
        ret = tpi.TPI_SetEvent(self.conn.hcon, info, cmdcode, subcmdcode, param1, param1len, param2, param2len)
        return (ret,)

    def bulkUpdate(self, ctlfilename):
        ret = tpi.TPI_BulkUpdate(self.conn.hcon, ctlfilename)
        return (ret,)

    def setKeyWordMarkPara(self, prefix, suffix, segwordsdicts, markdict):
        ret = tpi.TPI_SetKeyWordMarkPara(self.cur.hset, prefix, suffix, segwordsdicts, markdict)
        return (ret,)

    def markKeyWordEx(self, srcstring, prefix, suffix, segwordsdicts, markdict):
        srclen = len(srcstring)
        size = c_int(4096)
        buf = create_unicode_buffer(size.value)
        while True:
            ret = tpi.TPI_MarkKeyWordEx(self.conn.hcon, srcstring, srclen, prefix, suffix, segwordsdicts, markdict, buf, size)
            if ret == tpi.TPI_ERR_BUFFER:
                del (buf)
                size.value *= 2
                buf = create_unicode_buffer(size.value)
                continue
            elif ret >= 0:
                try:
                    return (ret, buf.value)
                except ValueError:
                    pos = 0
                    try:
                        for pos in range(size.value):
                            wstring_at(byref(buf, pos * sizeof(c_wchar)), 1)
                    except ValueError:
                        if 0 == pos:
                            return (ret, "")
                        pos = pos - 1
                        return (ret, wstring_at(buf, pos))
            else:
                return (ret,)
